package com.canaan.business.service.inOutStock.impl;

import cn.hutool.core.collection.CollUtil;
import com.canaan.business.common.enums.inOutStock.InOrderStatusEnum;
import com.canaan.business.common.enums.inOutStock.InOutStockTypeEnum;
import com.canaan.business.common.enums.inOutStock.InStockOrderTypeEnum;
import com.canaan.business.common.enums.storehouse.InOutStorageOperationEnum;
import com.canaan.business.domain.bill.AdjustInBill;
import com.canaan.business.domain.bill.RefundProductBill;
import com.canaan.business.domain.bill.SalesRefundBill;
import com.canaan.business.domain.bill.ScrapProductBill;
import com.canaan.business.domain.inOutStock.WmsInStockDetailOrder;
import com.canaan.business.domain.inOutStock.WmsInStockOrder;
import com.canaan.business.domain.invoice.WmsProStockApply;
import com.canaan.business.domain.storehouse.StockCheckDiff;
import com.canaan.business.domain.storehouse.WmsInOutStorage;
import com.canaan.business.domain.storehouse.WmsStorehouseStock;
import com.canaan.business.domain.vo.StockDetailProductVo;
import com.canaan.business.domain.vo.WmsInStockOrderVo;
import com.canaan.business.mapper.inOutStock.WmsInStockOrderMapper;
import com.canaan.business.service.bill.IAdjustInBillService;
import com.canaan.business.service.bill.IRefundProductBillService;
import com.canaan.business.service.bill.ISalesRefundBillService;
import com.canaan.business.service.bill.IScrapProductBillService;
import com.canaan.business.service.inOutStock.IWmsInStockDetailOrderService;
import com.canaan.business.service.inOutStock.IWmsInStockOrderService;
import com.canaan.business.service.invoice.IWmsProStockApplyService;
import com.canaan.business.service.storehouse.IWmsInOutStorageService;
import com.canaan.business.service.storehouse.IWmsStorehouseStockService;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.common.utils.TableNoUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 入库单Service业务层处理
 *
 * @author ruoyi
 * @date 2022-12-20
 */
@Service
public class WmsInStockOrderServiceImpl implements IWmsInStockOrderService
{
    @Resource
    private WmsInStockOrderMapper wmsInStockOrderMapper;

    @Resource
    private IWmsInStockDetailOrderService wmsInStockDetailOrderService;
    @Resource
    private IWmsStorehouseStockService wmsStorehouseStockService;
    @Resource
    private IWmsProStockApplyService wmsProStockApplyService;
    @Resource
    private IRefundProductBillService refundProductBillService;
    @Resource
    private IScrapProductBillService scrapProductBillService;
    @Resource
    private ISalesRefundBillService salesRefundBillService;
    @Resource
    private IAdjustInBillService adjustInBillService;
    @Resource
    private IWmsInOutStorageService wmsInOutStorageService;

    /**
     * 查询入库单
     *
     * @param id 入库单主键
     * @return 入库单
     */
    @Override
    public WmsInStockOrder selectWmsInStockOrderById(Long id)
    {
        return wmsInStockOrderMapper.selectWmsInStockOrderById(id);
    }

    /**
     * 查询入库单
     *
     * @param no 入库单编号
     * @return 入库单
     */
    @Override
    public WmsInStockOrder selectWmsInStockOrderByNo(String no)
    {
        return wmsInStockOrderMapper.selectWmsInStockOrderByNo(no);
    }

    /**
     * 查询入库单列表
     *
     * @param wmsInStockOrder 入库单
     * @return 入库单
     */
    @Override
    public List<WmsInStockOrder> selectWmsInStockOrderList(WmsInStockOrder wmsInStockOrder)
    {
        return wmsInStockOrderMapper.selectWmsInStockOrderList(wmsInStockOrder);
    }

    /**
     * 新增入库单
     *
     * @param wmsInStockOrder 入库单
     * @return 结果
     */
    @Override
    public int insertWmsInStockOrder(WmsInStockOrder wmsInStockOrder)
    {
        wmsInStockOrder.setCreateTime(DateUtils.getNowDate());
        wmsInStockOrder.setCreateBy(SecurityUtils.getUsername());
        if (StringUtils.isEmpty(wmsInStockOrder.getNo())){
            wmsInStockOrder.setNo(TableNoUtil.getNo(WmsInStockOrder.class));
        }
        if (wmsInStockOrder.getOrderStatus()!=InOrderStatusEnum.ACCOMPLISH.getCode()){
            wmsInStockOrder.setOrderStatus(InOrderStatusEnum.NEW.getCode());
        }
        return wmsInStockOrderMapper.insertWmsInStockOrder(wmsInStockOrder);

    }

    /**
     * 修改入库单
     *
     * @param wmsInStockOrder 入库单
     * @return 结果
     */
    @Override
    public int updateWmsInStockOrder(WmsInStockOrder wmsInStockOrder)
    {
        wmsInStockOrder.setUpdateTime(DateUtils.getNowDate());
        wmsInStockOrder.setUpdateBy(SecurityUtils.getUsername());
        return wmsInStockOrderMapper.updateWmsInStockOrder(wmsInStockOrder);
    }

    /**
     * 入库单取消
     *
     * @param wmsInStockOrder 入库单
     * @return 结果
     */
    @Override
    public int cancel(WmsInStockOrder wmsInStockOrder)
    {
        String cause = wmsInStockOrder.getRemark();
        if(StringUtils.isEmpty(cause)){
            throw new ServiceException("取消原因不能为空");
        }
        wmsInStockOrder = wmsInStockOrderMapper.selectWmsInStockOrderById(wmsInStockOrder.getId());
        if(wmsInStockOrder == null){
            return 0;
        }else if(!InOrderStatusEnum.NEW.getCode().equals(wmsInStockOrder.getOrderStatus())) {
            throw new ServiceException("只有新建状态才能取消");
        }

        if(StringUtils.isNotEmpty(wmsInStockOrder.getRelOrderNo())){
            if(InStockOrderTypeEnum.PRODUCTION.getCode().equals(wmsInStockOrder.getOrderType())){
                //生产入库
                WmsProStockApply proStockApply = new WmsProStockApply();
                proStockApply.setNo(wmsInStockOrder.getRelOrderNo());
                List<WmsProStockApply> applyList = wmsProStockApplyService.selectWmsProStockApplyList(proStockApply);
                if(!applyList.isEmpty()){
                    proStockApply = applyList.get(0);
                    proStockApply.setOrderStatus(InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode());
                    proStockApply.setRemark(cause);
                    wmsProStockApplyService.updateWmsProStockApply(proStockApply);
                }
            }else if(InStockOrderTypeEnum.STORES_RETURNED.getCode().equals(wmsInStockOrder.getOrderType())){
                //退料库
                RefundProductBill bill = refundProductBillService.selectRefundProductBillByNo(wmsInStockOrder.getRelOrderNo());
                if(bill != null) {
                    bill.setStatus(InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode());
                    bill.setRemark(cause);
                    refundProductBillService.updateRefundProductBill(bill);
                }
            }else if(InStockOrderTypeEnum.SCRAP.getCode().equals(wmsInStockOrder.getOrderType())){
                //报废入库
                ScrapProductBill bill = scrapProductBillService.selectScrapProductBillByNo(wmsInStockOrder.getRelOrderNo());
                if(bill != null) {
                    bill.setStatus(InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode());
                    bill.setRemark(cause);
                    scrapProductBillService.updateScrapProductBill(bill);
                }
            }else if(InStockOrderTypeEnum.SALES_REFUND.getCode().equals(wmsInStockOrder.getOrderType())){
                //销售退货入库
                SalesRefundBill bill = salesRefundBillService.selectSalesRefundBillByNo(wmsInStockOrder.getRelOrderNo());
                if(bill != null) {
                    bill.setStatus(InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode());
                    bill.setRemark(cause);
                    salesRefundBillService.updateSalesRefundBill(bill);
                }
            }else if(InStockOrderTypeEnum.ALLOCATE.getCode().equals(wmsInStockOrder.getOrderType())){
                //调拨入库
                AdjustInBill bill = adjustInBillService.selectAdjustInBillByNo(wmsInStockOrder.getRelOrderNo());
                if(bill != null) {
                    bill.setStatus(InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode());
                    bill.setRemark(cause);
                    adjustInBillService.updateAdjustInBill(bill);
                }
            }
        }
        //修改状态
        wmsInStockOrder.setRemark(null);
        wmsInStockOrder.setOrderStatus(InOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode());
        wmsInStockOrder.setUpdateTime(DateUtils.getNowDate());
        wmsInStockOrder.setUpdateBy(SecurityUtils.getUsername());
        return wmsInStockOrderMapper.updateWmsInStockOrder(wmsInStockOrder);
    }

    /**
     * 批量删除入库单
     *
     * @param ids 需要删除的入库单主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteWmsInStockOrderByIds(Long[] ids)
    {
        WmsInStockOrder params = new WmsInStockOrder();
        params.setIds(Arrays.asList(ids));
        List<WmsInStockOrder> list = this.selectWmsInStockOrderList(params);
        if(list.isEmpty()){
            return 0;
        }
        List<WmsInStockOrder> errorList = list.stream()
                .filter(e -> e.getTotalActualQty() > 0 || InOrderStatusEnum.ACCOMPLISH.getCode().equals(e.getOrderStatus()))
                .collect(Collectors.toList());
        if(!errorList.isEmpty()){
            throw new ServiceException("已完成状态或已有实际入库数量的数据不能删除");
        }

        int response = wmsInStockOrderMapper.deleteWmsInStockOrderByIds(ids);
        if(response > 0){
            //删除对应的详情信息
            List<String> nos = list.stream().map(WmsInStockOrder::getNo).collect(Collectors.toList());
            wmsInStockDetailOrderService.deleteByOrderNos(nos);
        }
        return response;
    }

    /**
     * 删除入库单信息
     *
     * @param id 入库单主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteWmsInStockOrderById(Long id)
    {
        WmsInStockOrder entity = this.selectWmsInStockOrderById(id);
        if(entity == null){
            return 0;
        }else if(InOrderStatusEnum.ACCOMPLISH.getCode().equals(entity.getOrderStatus())){
            throw new ServiceException("已完成状态不能删除");
        }else if(entity.getTotalActualQty() > 0){
            throw new ServiceException("已有实际入库数量不能删除");
        }
        int response = wmsInStockOrderMapper.deleteWmsInStockOrderById(id);
        if(response > 0){
            //删除对应的详情信息
            wmsInStockDetailOrderService.deleteByOrderNos(Collections.singletonList(entity.getNo()));
        }
        return response;
    }


    /**
     * 导出列表查询
     * @param entity    参数
     * @return 导出列表
     */
    @Override
    public List<WmsInStockOrderVo> exportList(WmsInStockOrder entity) {
        return wmsInStockOrderMapper.exportList(entity);
    }

    @Override
    public WmsInStockOrder selectWmsInStockOrderByRelOrderNo(String no, Integer code) {
        return wmsInStockOrderMapper.selectWmsInStockOrderByRelOrderNo(no,code);
    }

    @Override
    public void initBillStockOrder(String relOrderNo, Integer orderType,String CustomerNo, List<StockDetailProductVo> stockDetailProductVos) {
        WmsInStockOrder wmsInStockOrder = new WmsInStockOrder();
        wmsInStockOrder.setRelOrderNo(relOrderNo);
        wmsInStockOrder.setOrderType(orderType);
        if(StringUtils.isNotEmpty(CustomerNo)){
            wmsInStockOrder.setCustomerNo(CustomerNo);
        }
        wmsInStockOrder.setTotalQty(stockDetailProductVos.stream().mapToLong(e->e.getOrderQty()).sum());
        this.insertWmsInStockOrder(wmsInStockOrder);
        List<WmsInStockDetailOrder> wmsInStockDetailOrders = new ArrayList<>();
        for (int i = 0; i < stockDetailProductVos.size(); i++) {
            StockDetailProductVo stockDetailProductVo = stockDetailProductVos.get(i);
            WmsInStockDetailOrder wmsInStockDetailOrder = new WmsInStockDetailOrder();
            wmsInStockDetailOrder.setOrderNo(wmsInStockOrder.getNo());
            wmsInStockDetailOrder.setProductNo(stockDetailProductVo.getProductNo());
            wmsInStockDetailOrder.setOrderDetailStatus(InOrderStatusEnum.NEW.getCode());
            wmsInStockDetailOrder.setOrderQty(stockDetailProductVo.getOrderQty());
            wmsInStockDetailOrder.setActualQty(0l);
            wmsInStockDetailOrder.setSort(i+1);
            wmsInStockDetailOrders.add(wmsInStockDetailOrder);
        }
        if (CollUtil.isNotEmpty(wmsInStockDetailOrders)){
            this.wmsInStockDetailOrderService.batchInsertInStockDetailOrder(wmsInStockDetailOrders);
        }
    }

    /**
     * 直接入库
     * @author 梁建设
     * @since 2023/2/16 下午5:25
     */
    @Override
    public WmsInStockOrder directInStock(String relOrderNo, Integer orderType, List<StockCheckDiff> stockDetailProductVos, String remark) {
        if (CollUtil.isEmpty(stockDetailProductVos)){
            return null;
        }
        WmsInStockOrder wmsInStockOrder = new WmsInStockOrder();
        wmsInStockOrder.setRelOrderNo(relOrderNo);
        wmsInStockOrder.setOrderStatus(InOrderStatusEnum.ACCOMPLISH.getCode());
        wmsInStockOrder.setOrderType(orderType);
        wmsInStockOrder.setTotalQty(stockDetailProductVos.stream().mapToLong(e->e.getCheckQty()-e.getStockQty()).sum());
        wmsInStockOrder.setTotalActualQty(stockDetailProductVos.stream().mapToLong(e->e.getCheckQty()-e.getStockQty()).sum());
        wmsInStockOrder.setCompleteTime(new Date());
        wmsInStockOrder.setCause(remark);
        wmsInStockOrder.setRemark(remark);
        this.insertWmsInStockOrder(wmsInStockOrder);
        List<WmsInStockDetailOrder> wmsInStockDetailOrders = new ArrayList<>();
        for (int i = 0; i < stockDetailProductVos.size(); i++) {
            StockCheckDiff stockDetailProductVo = stockDetailProductVos.get(i);
            WmsInStockDetailOrder wmsInStockDetailOrder = new WmsInStockDetailOrder();
            wmsInStockDetailOrder.setOrderNo(wmsInStockOrder.getNo());
            wmsInStockDetailOrder.setProductNo(stockDetailProductVo.getProductNo());
            wmsInStockDetailOrder.setOrderDetailStatus(InOrderStatusEnum.ACCOMPLISH.getCode());
            wmsInStockDetailOrder.setOrderQty(stockDetailProductVo.getCheckQty()-stockDetailProductVo.getStockQty());
            wmsInStockDetailOrder.setActualQty(stockDetailProductVo.getCheckQty()-stockDetailProductVo.getStockQty());
            wmsInStockDetailOrder.setSort(i+1);
            wmsInStockDetailOrders.add(wmsInStockDetailOrder);
        }
        this.wmsInStockDetailOrderService.batchInsertInStockDetailOrder(wmsInStockDetailOrders);
        for (StockCheckDiff stockCheckDiff : stockDetailProductVos) {
            //默认生成一条入库库流水记录
            WmsInOutStorage inStorage = new WmsInOutStorage();
            inStorage.setNo(TableNoUtil.getNo(WmsInOutStorage.class));
            inStorage.setProductNo(stockCheckDiff.getProductNo());
            inStorage.setProductName(stockCheckDiff.getProductName());
            inStorage.setProductUnit(stockCheckDiff.getProductUnit());
            inStorage.setStorehouseNo(stockCheckDiff.getStorehouseNo());
            inStorage.setAreaNo(stockCheckDiff.getAreaNo());
            inStorage.setStorehouseLocationNo(stockCheckDiff.getLocationNo());
            WmsStorehouseStock storehouseStock = this.wmsStorehouseStockService.selectWmsStorehouseStockListByBarcode(stockCheckDiff.getBarcode());
            if (storehouseStock!=null){
                inStorage.setBatchNo(storehouseStock.getBatchNo());
            }
            inStorage.setBarcode(stockCheckDiff.getBarcode());
            inStorage.setQuantity(stockCheckDiff.getCheckQty()-stockCheckDiff.getStockQty());
            inStorage.setRelNo(wmsInStockOrder.getNo());
            inStorage.setType(InOutStockTypeEnum.OTHER_IN.getCode().longValue());
            inStorage.setOperation(InOutStorageOperationEnum.IN.getCode());
            wmsInOutStorageService.insertWmsInOutStorageWithStock(inStorage);
        }
        return wmsInStockOrder;
    }

    /**
     * 删除入库单信息
     *
     * @param relOrderNos 来源单据编号
     * @param orderType 对应的入库单类型
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteWmsInStockOrderByRelOrderNosAndType(List<String> relOrderNos, Integer orderType){
        if(CollUtil.isEmpty(relOrderNos) || orderType == null){
            return 0;
        }
        //取关联的入库单列表
        WmsInStockOrder inStockOrder = new WmsInStockOrder();
        inStockOrder.setOrderType(orderType);
        inStockOrder.setParams(Collections.singletonMap("relOrderNos", relOrderNos));
        List<WmsInStockOrder> inStockOrderList = this.selectWmsInStockOrderList(inStockOrder);
        if(inStockOrderList.isEmpty()){
            return 0;
        }
        //取关联的入库单明细列表
        List<String> inStockOrderNos = inStockOrderList.stream().map(WmsInStockOrder::getNo).collect(Collectors.toList());
        WmsInStockDetailOrder inStockDetailOrder = new WmsInStockDetailOrder();
        inStockDetailOrder.setParams(Collections.singletonMap("orderNos", inStockOrderNos));
        List<WmsInStockDetailOrder> inStockDetailOrderList = wmsInStockDetailOrderService.selectWmsInStockDetailOrderList(inStockDetailOrder);

        Long[] orderIdArray = inStockOrderList.stream().map(WmsInStockOrder::getId).toArray(Long[]::new);
        int respones = this.deleteWmsInStockOrderByIds(orderIdArray);
        //明细不为空的话就进行删除
        if(!inStockDetailOrderList.isEmpty()){
            Long[] detailIdArray = inStockDetailOrderList.stream().map(WmsInStockDetailOrder::getId).toArray(Long[]::new);
            wmsInStockDetailOrderService.deleteWmsInStockDetailOrderByIds(detailIdArray);
        }
        return respones;
    }

    @Override
    public Integer getTodayCompletedNum(String storehouseNo) {
        return this.wmsInStockOrderMapper.getTodayCompletedNum(storehouseNo);
    }

    @Override
    public Integer getWaitInStockNum(String storehouseNo) {
        return this.wmsInStockOrderMapper.getWaitInStockNum(storehouseNo);
    }

}
